/**
 * Project: Utilities <br>
 * Package: org.leumasjaffe.collections.map
 */
package org.leumasjaffe.collections.map;

import java.util.Comparator;
import java.util.List;
import java.util.SortedMap;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
 * Class org.leumasjaffe.collections.map..AbstractSortedMultiMap in file AbstractSortedMultiMap.java <br>
 * 
 * @author leumasjaffe
 * @version Feb 1, 2014
 * Created on: Feb 1, 2014
 * 
 */
@NonNullByDefault
public class DelegateSortedMultiMap<K, V> extends DelegateMultiMap<K, V> implements
		SortedMultiMap<K, V> {
	private final SortedMap<K, List<V>> sortedInternalMap;
	protected transient int modCount = 0;
	
	protected class SortedSubMultiMap extends DelegateSortedMultiMap<K, V> {
		private int size = -1;
		private transient int expetedModCount = DelegateSortedMultiMap.this.modCount;
		
		/**
		 * @param internalMap
		 */
		protected SortedSubMultiMap(SortedMap<K, List<V>> internalMap) {
			super(internalMap);
		}
		
		/* (non-Javadoc)
		 * @see org.leumasjaffe.collections.map.AbstractMultiMap#size()
		 */
		@Override
		public int size() {
			recalcSize();
			return this.size;
		}

		/**
		 * 
		 */
		private void recalcSize() {
			if (this.size == -1 || 
					this.expetedModCount != DelegateSortedMultiMap.this.modCount) {
				this.size = 0;
				for (List<V> list : DelegateSortedMultiMap.this.sortedInternalMap.values()) {
					this.size += list.size();
				}
				this.expetedModCount = DelegateSortedMultiMap.this.modCount;
			}
		}
		
	}

	/**
	 * @param internalMap
	 */
	protected DelegateSortedMultiMap(SortedMap<K, List<V>> internalMap) {
		super(internalMap);
		this.sortedInternalMap = internalMap;
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#comparator()
	 */
	@Override
	public @Nullable Comparator<? super K> comparator() {
		return this.sortedInternalMap.comparator();
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#subMap(java.lang.Object, java.lang.Object)
	 */
	@SuppressWarnings("null")
	@Override
	public SortedMap<K, V> subMap(@Nullable K fromKey, @Nullable K toKey) {
		return new SortedSubMultiMap(this.sortedInternalMap.subMap(fromKey, toKey));
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#headMap(java.lang.Object)
	 */
	@SuppressWarnings("null")
	@Override
	public SortedMap<K, V> headMap(@Nullable K toKey) {
		return new SortedSubMultiMap(this.sortedInternalMap.headMap(toKey));
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#tailMap(java.lang.Object)
	 */
	@SuppressWarnings("null")
	@Override
	public SortedMap<K, V> tailMap(@Nullable K fromKey) {
		return new SortedSubMultiMap(this.sortedInternalMap.tailMap(fromKey));
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#firstKey()
	 */
	@SuppressWarnings("null")
	@Override
	public K firstKey() {
		return this.sortedInternalMap.firstKey();
	}

	/* (non-Javadoc)
	 * @see java.util.SortedMap#lastKey()
	 */
	@SuppressWarnings("null")
	@Override
	public K lastKey() {
		return this.sortedInternalMap.lastKey();
	}
	
	/* (non-Javadoc)
	 * @see java.util.MultiMap#get(java.lang.Object)
	 */
	@Override
	public List<V> getAll(@Nullable K key) {
		return (List<V>) super.getAll(key);
	}

}
